#include <SFML/Graphics/CircleShape.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <nice2d/spritedecorator.h>
#include <nice2d/util.h>

IMPLEMENT_OBJECT(SpriteRingDecorator,SpriteDecorator)

class SpriteRingData
{
public:
    SpriteRingData()
    {
        circle.setPointCount(100);
        circle.setFillColor(sf::Color::Transparent);
        circle.setOutlineThickness(1.0f);
        circle.setOutlineColor(sf::Color::Blue);
    }

    float scaleFactor = 1.0f;
    sf::CircleShape circle;
};

SpriteRingDecorator::SpriteRingDecorator():
    SpriteDecorator(),
    data(new SpriteRingData())
{
}

SpriteRingDecorator::~SpriteRingDecorator()
{
}

void SpriteRingDecorator::setScaleFactor(float factor)
{
    if (factor > 0.0f)
        data->scaleFactor = factor;
}

float SpriteRingDecorator::getScaleFactor()const
{
    return data->scaleFactor;
}

void SpriteRingDecorator::setOutlineThickness(float thickness)
{
    data->circle.setOutlineThickness(thickness);
}

float SpriteRingDecorator::getOutlineThickness()const
{
    return data->circle.getOutlineThickness();
}

void SpriteRingDecorator::setOutlineColor(const sf::Color &color)
{
    data->circle.setOutlineColor(color);
}

sf::Color SpriteRingDecorator::getOutlineColor()const
{
    return data->circle.getOutlineColor();
}

void SpriteRingDecorator::setFillColor(const sf::Color &color)
{
    data->circle.setFillColor(color);
}

sf::Color SpriteRingDecorator::getFillColor()const
{
    return data->circle.getFillColor();
}

PTree SpriteRingDecorator::serialize()
{
    PTree node;
    node.add("scaleFactor", getScaleFactor());
    node.add("outlineThickness", getOutlineThickness());
    node.add_child("outlineColor",serializeObject(getOutlineColor()));
    node.add_child("fillColor",serializeObject(getFillColor()));
    return node;
}

void SpriteRingDecorator::deserialize(const PTree &node)
{
    setScaleFactor(node.get<float>("scaleFactor"));
    setOutlineThickness(node.get<float>("outlineThickness"));
    setOutlineColor(deserializeColor(node.get_child("outlineColor")));
    setFillColor(deserializeColor(node.get_child("fillColor")));
}

void SpriteRingDecorator::update()
{
    auto sprite = getSprite().lock();
    auto box = sprite->getBoundingBox();

    auto spriteCenter = getRectCenter(box);
    float radius = distance(spriteCenter,sf::Vector2f(box.left,box.top)) * data->scaleFactor;
    data->circle.setRadius(radius);

    auto circleBox = data->circle.getGlobalBounds();
    data->circle.setPosition(-circleBox.left-radius+box.width*0.5f,-circleBox.top-radius+box.height*0.5f);
}

void SpriteRingDecorator::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
    target.draw(data->circle, states);
}
